/*
 * @Author: soso
 * @Date: 2022-01-24 11:47:54
 * @LastEditTime: 2022-03-01 10:49:12
 * @LastEditors: Please set LastEditors
 * @Description: 同步文件相关操作
 * @FilePath: /sync-client/comm/sync.go
 */

package comm

import (
	"gomeshcli/comm/command"
	"gomeshcli/comm/defines"
	"gomeshcli/sconfig"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"

	"gitee.com/kimsoso/go-utils/utils"
	"github.com/vmihailenco/msgpack"
)

type SsyncDirs struct {
	Files map[string]*command.Ufile
	Path  string
}

func NewSsyncDirs(path string) SsyncDirs {
	ss := SsyncDirs{}
	ss.Path = path
	ss.Files = map[string]*command.Ufile{}
	// ss.loadFilesSEQ()
	return ss
}

func (ss SsyncDirs) InitFiles() {
	for k := range ss.Files {
		delete(ss.Files, k)
	}
}

// 获得监测目录某个目录的文件列表(含.)
func (ss SsyncDirs) GetDirFiles(relPath string) {
	realPath := filepath.Clean(filepath.Join(sconfig.SConfig.WatchDir, relPath))

	files := utils.GetAllFiles(realPath)
	if len(files) == 0 {
		return
	}
	for _, fpath := range files {
		if strings.HasSuffix(fpath, defines.DirFlagFile) {
			continue
		}

		ufile := command.Ufile{}
		rdir, _ := filepath.Rel(realPath, fpath)
		ufile.Path = rdir
		fi, _ := os.Stat(fpath)
		if fi.IsDir() {
			ufile.FileType = command.IsDir
		} else {
			ufile.FileType = command.IsFile
			ufile.FileSize = fi.Size()
		}
		ss.Files[rdir] = &ufile
	}
}

// 写入命令文件序列
func (ss SsyncDirs) writeFilesSEQ() {
	buf, _ := msgpack.Marshal(ss.Files)
	ioutil.WriteFile(ss.Path, buf, os.ModePerm)
}

// 删除磁盘已存储的文件序列
func (ss SsyncDirs) removeFilesSEQ() {
	os.RemoveAll(ss.Path)
}

// 从磁盘加载命令序列
// func (ss SsyncDirs) loadFilesSEQ() {
// 	buf, err := ioutil.ReadFile(ss.Path)
// 	if err != nil {
// 		return
// 	}
// 	yaml.Unmarshal(buf, &(ss.Files))
// }

// 往节点发送文件序列
func (ss SsyncDirs) sendFilesSEQ() {
	sfiles := []*sconfig.Sfile{}

	for _, file := range ss.Files {
		fi, err := os.Stat(file.Path)
		sfile := &sconfig.Sfile{
			IsDelete: os.IsNotExist(err),
			Path:     file.Path,
			Size:     fi.Size(),
		}

		if !sfile.IsDelete {
			sfile.IsDir = fi.IsDir()
		}

		sfiles = append(sfiles, sfile)
	}

	fpaths, _ := SendLocalExistFile(sfiles, sconfig.SConfig.GetHostPort())

	for path := range fpaths {
		_path, _ := filepath.Rel(filepath.Join(sconfig.SConfig.WatchDir, ss.Path), path)
		delete(ss.Files, filepath.Join(ss.Path, _path))
	}

	if len(ss.Files) == 0 {
		ss.removeFilesSEQ()
	} else {
		ss.writeFilesSEQ()
	}
}
